home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / language / sozobon2.zoo / hcc / gen.c < prev    next >
C/C++ Source or Header  |  1990-12-14  |  13KB  |  699 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    gen.c
  12.  *
  13.  *    Generate code.
  14.  *    Includes main routine and code generation for unary nodes
  15.  *    and leafs.
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include "param.h"
  20. #include "bstok.h"
  21. #include "tytok.h"
  22. #include "flags.h"
  23. #include "nodes.h"
  24. #include "gen.h"
  25.  
  26. NODEP strsave;
  27. int cctest;
  28. static int reserve;
  29. static int tmpused;
  30.  
  31. extern xflags[];
  32. #define debug xflags['g'-'a']
  33.  
  34. #define FAIL    0
  35. #define OKAY    1
  36.  
  37. #define isimmed(np)    ((np)->g_flags & IMMEDID)
  38. #define isareg(np)    ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
  39. #define isdreg(np)    ((np)->g_token == REGVAR && (np)->g_rno < AREG)
  40. #define istdreg(np)    ((np)->g_token == REGVAR && (np)->g_rno < DRV_START)
  41.  
  42. int cookflags[] = {
  43.     0,
  44.     NOVAL_OK|CC_OK|IMMA_OK,        /* FORSIDE */
  45.     IMMA_OK,            /* FORPUSH */
  46.     CC_OK,                /* FORCC */
  47.     IMMA_OK,            /* FORIMA */
  48.     0,                /* FORADR */
  49.     IMMA_OK,            /* FORINIT */
  50.     0,                /* IND0 */
  51.     0,                /* RETSTRU */
  52. };
  53.  
  54. genx(np, cookie)
  55. register NODEP np;
  56. {
  57.     extern nmerrors;
  58.     int rv;
  59.     extern NODE *blktab;
  60.  
  61.     if (np == NULL) return;
  62.     if (nmerrors)
  63.         goto bad;
  64.     if (debug) {
  65.         printf("GEN enter");
  66.         printnode(np);
  67.     }
  68.  
  69.     untype(np);
  70.     if (debug>1) {
  71.         printf("after UNTYPE");
  72.         printnode(np);
  73.     }
  74.  
  75.     tmpused = 0;
  76.     gunk(np);
  77.     if (tmpused && tmpused > blktab->b_tsize)
  78.         blktab->b_tsize = tmpused;
  79.     if (debug > 1) {
  80.         printf("after gunk");
  81.         printnode(np);
  82.     }
  83.     order(np);
  84.  
  85.     reserve = 0;
  86.     rv = eval(np, cookie);
  87.     if (rv == OKAY && debug) {
  88.         printf("GEN exit");
  89.         codeprint(np);
  90.     }
  91.     if (rv == OKAY)
  92.         rv = cookmon(np, cookie);
  93.     else
  94.         error("couldnt eval node");
  95.     freenode(np);
  96.     return rv;
  97. bad:
  98.     freenode(np);
  99.     return FAIL;
  100. }
  101.  
  102. eval(np, cookie)
  103. register NODEP np;
  104. {
  105.     int rv;
  106.  
  107.     np->g_r1 = np->g_r2 = -1;
  108.  
  109.     if (np == NULL) return FAIL;
  110.  
  111.     switch (np->g_type) {
  112.  
  113.     default:
  114.         rv = b_eval(np, cookie);
  115.         /* already did freetmps */
  116.         free1(np, np->n_left);
  117.         free1(np, np->n_right);
  118.         break;
  119.  
  120.     case EV_LEFT:
  121.         rv = u_eval(np, cookie);
  122.         freetmps(np);
  123.         free1(np, np->n_left);
  124.         break;
  125.  
  126.     case EV_NONE:
  127.         rv = l_eval(np);
  128.         break;
  129.     }
  130.     return rv;
  131. }
  132.  
  133. u_eval(np, cookie)
  134. register NODEP np;
  135. {
  136.     int subcook = FORADR;
  137.  
  138.     switch (np->g_token) {
  139.     case STAR:
  140.         subcook = FORIMA;
  141.         break;
  142.     case '!':
  143.         subcook = FORCC;
  144.         break;
  145.     }
  146.  
  147.     if (eval(np->n_left, subcook) == FAIL)
  148.         return FAIL;
  149.     return u_sube(np, cookflags[cookie]);
  150. }
  151.  
  152. u_sube(np, flags)
  153. register NODEP np;
  154. {
  155.     register NODEP lp = np->n_left;
  156.     long offs;
  157.     int i;
  158.  
  159.     switch (np->g_token) {
  160.     case '.':
  161.         if (np->g_fldw)
  162.             return fldget(np, flags);
  163.         offs = np->g_offs;
  164.         inherit(np);
  165.         np->g_offs += offs;
  166.         return OKAY;
  167.     case STAR:
  168.         if (isimmed(lp)) {
  169.             inherit(np);
  170.             np->g_flags &= ~IMMEDID;
  171.         } else if (isareg(lp)) {
  172.             indir(np, lp->g_rno);
  173.         } else {    /* NEED A temp */
  174.             if (lp->g_token == OREG && istemp(lp->g_rno))
  175.                 i = lp->g_rno;
  176.             else
  177.                 i = ralloc(AREG);
  178.             addcode(np, "\tmove.l\t<A,R0\n");
  179.             indir(np, i);
  180.         }
  181.         return OKAY;
  182.     case UNARY '&':
  183.         if (isimmed(lp))
  184.             warn("& ignored");
  185.         else if (lp->g_token == REGVAR)
  186.             return FAIL;
  187.         inherit(np);
  188.         np->g_flags |= IMMEDID;
  189.         if ((flags & IMMA_OK) == 0)
  190.             imm_oreg(np);
  191.         return OKAY;
  192.     case '~':
  193.         utemp(np);
  194.         addcode(np, "\tnot.S\tA\n");
  195.         cc_hack(np);
  196.         return OKAY;
  197.     case UNARY '-':
  198.         utemp(np);
  199.         addcode(np, "\tneg.S\tA\n");
  200.         cc_hack(np);
  201.         return OKAY;
  202.     case TCONV:
  203.         castgen(np);
  204.         return OKAY;
  205.     case PUSHER:    /* must not be on left of assign or asn-op */
  206.         if ((lp->g_token != OREG && lp->g_token != REGVAR) ||
  207.             istemp(lp->g_rno) == 0) {
  208.             inherit(np);
  209.             return OKAY;
  210.         }
  211.         if (lp->g_ty == ET_A)
  212.             strxpush(np);
  213.         else
  214.             addcode(np, "\tmove.S\t<A,-(sp)\n");
  215.         return OKAY;
  216.     case '(':
  217.         if (np->g_ty == ET_A) {        /* struct returned */
  218.             frc_ral(AREG);
  219.             indir(np, AREG);
  220.         } else {
  221.             frc_ral(0);
  222.             retreg(np, 0);
  223.         }
  224.         addcode(np, "\tjsr\t<A\n");
  225.         return OKAY;
  226.     case DOUBLE '+':
  227.         holdcon(np);
  228.         inherit(np);
  229.         addcode(np, "\tadd.S\t#K,A\n");
  230.         cc_hack(np);
  231.         return OKAY;
  232.     case DOUBLE '-':
  233.         holdcon(np);
  234.         inherit(np);
  235.         addcode(np, "\tsub.S\t#K,A\n");
  236.         cc_hack(np);
  237.         return OKAY;
  238.     case POSTINC:
  239.         if ((flags & NOVAL_OK) == 0) {
  240.             i = ralloc(0);
  241.             retreg(np, i);
  242.             addcode(np, "\tmove.S\t<A,A\n");
  243.         }
  244.         addcode(np, "\tadd.S\t#O,<A\n");
  245.         return OKAY;
  246.     case POSTDEC:
  247.         if ((flags & NOVAL_OK) == 0) {
  248.             i = ralloc(0);
  249.             retreg(np, i);
  250.             addcode(np, "\tmove.S\t<A,A\n");
  251.         }
  252.         addcode(np, "\tsub.S\t#O,<A\n");
  253.         return OKAY;
  254.     case CMPBR:
  255.         i = ralloc(0);
  256.         retreg(np, i);
  257.         addcode(np, "\tsN\tA\n\tand.w\t#1,A\n");
  258.         cc_hack(np);
  259.         return OKAY;
  260.     case '!':
  261.         if (flags & CC_OK) {
  262.             if (iscc(lp)) {
  263.                 i = cctok(lp);
  264.                 i = (i&1) ? i+1 : i-1;    /* reverse truth */
  265.             } else {
  266.                 i = B_EQ;
  267.                 addcode(np, "<Q");
  268.             }
  269.             np->g_token = i + BR_TOK;
  270.         } else {
  271.             if (istdreg(lp))
  272.                 i = lp->g_rno;
  273.             else
  274.                 i = ralloc(0);
  275.             retreg(np, i);
  276.             if (iscc(lp)) {
  277.                 addcode(np, "<EA\n\tand.w\t#1,A\n");
  278.             } else {
  279.                 addcode(np, "<Q");
  280.                 addcode(np, "\tseq\tA\n\tand.w\t#1,A\n");
  281.             }
  282.         }
  283.         return OKAY;
  284.     default:
  285.         printf("Weird u_eval %s ", np->n_name);
  286.         return FAIL;
  287.     }
  288. }
  289.  
  290. holdcon(np)
  291. NODEP np;
  292. {
  293.     np->g_bsize = np->g_offs;
  294. }
  295.  
  296. retreg(np, rno)
  297. NODEP np;
  298. {
  299.     np->g_token = REGVAR;
  300.     np->g_rno = rno;
  301. }
  302.  
  303. indir(np, rno)
  304. register NODEP np;
  305. {
  306.     np->g_token = OREG;
  307.     np->g_offs = 0;
  308.     np->g_rno = rno;
  309. }
  310.  
  311. inherit(np)
  312. register NODEP np;
  313. {
  314.     NODEP lp = np->n_left;
  315.  
  316.     np->g_token = lp->g_token;
  317.     np->g_offs = lp->g_offs;
  318.     np->g_rno = lp->g_rno;
  319.     np->g_flags |= CHILDNM | (lp->g_flags & IMMEDID);
  320. }
  321.  
  322. cookmon(np, cookie)
  323. register NODEP np;
  324. {
  325.     extern FILE *output;
  326.  
  327.     if (np == NULL) return FAIL;
  328.  
  329.     switch (cookie) {
  330.     case FORCC:
  331.         if (iscc(np)) {
  332.             outcode(np);
  333.             cctest = cctok(np);
  334.         } else {
  335.             if (np->g_token == ICON && isimmed(np)) {
  336.                 cctest = np->g_offs ? B_YES : B_NO;
  337.                 return OKAY;
  338.             }
  339.             outcode(np);
  340.             outsub("Q", np);
  341.             cctest = B_NE;
  342.         }
  343.         return OKAY;
  344.     case FORINIT:
  345.         if (anycode(np) == 0 && (np->g_flags & IMMEDID)) {
  346.             out_a(np, output);
  347.             return OKAY;
  348.         }
  349.         error("bad INIT expr");
  350.         return FAIL;
  351.     case IND0:
  352.         outcode(np);
  353.         if (np->g_token != REGVAR ||
  354.             np->g_rno != 0)
  355.             if (np->g_token == ICON && np->g_offs == 0 &&
  356.                 isimmed(np))
  357.                 outsub("\tclr.S\td0\n", np);
  358.             else
  359.                 outsub("\tmove.S\tA,d0\n", np);
  360.         return OKAY;
  361.     case RETSTRU:
  362.         freetmps(np);
  363.         strret(np);
  364.         outcode(np);
  365.         return OKAY;
  366.     }
  367.     outcode(np);
  368.     return OKAY;
  369. }
  370.  
  371. anycode(np)
  372. register NODEP np;
  373. {
  374.     if (np->g_code)
  375.         return 1;
  376.     switch (np->g_type) {
  377.     case EV_NONE:
  378.         return 0;
  379.     case EV_LEFT:
  380.         return anycode(np->n_left);
  381.     case EV_RIGHT:
  382.         return anycode(np->n_right);
  383.     case EV_LR:
  384.     case EV_RL:
  385.         return anycode(np->n_left) || anycode(np->n_right);
  386.     }
  387. }
  388.  
  389. l_eval(np)
  390. register NODEP np;
  391. {
  392.     int l1;
  393.  
  394.     switch (np->g_token) {
  395.     case ID:
  396.         switch (np->g_sc) {
  397.         default:    /* EXTERN or HERE */
  398.             np->g_token = ONAME;
  399.             np->g_offs = 0;
  400.             if (np->n_name[0] != '%')
  401.                 nnmins(np, "_");
  402.             else    /* hack for inline name */
  403.                 strcpy(np->n_name, &np->n_name[1]);
  404.             return OKAY;        /* dont free n_nmx */
  405.         case K_STATIC:
  406.             sprintf(np->n_name, "L%d", (int)np->g_offs);
  407.             np->g_offs = 0;
  408.             np->g_token = ONAME;
  409.             break;
  410.         case K_AUTO:
  411.             np->g_rno = FRAMEP;
  412.             np->g_token = OREG;
  413.             break;
  414.         case K_REGISTER:
  415.             np->g_token = REGVAR;
  416.             break;
  417.         }
  418.         if (np->n_nmx) {
  419.             freenode(np->n_nmx);
  420.             np->n_nmx = NULL;
  421.         }
  422.         return OKAY;
  423.     case ICON:
  424.         np->g_flags |= IMMEDID;
  425.         return OKAY;
  426.     case FCON